package com.java.java8.func.reduce;

import com.google.common.collect.Lists;
import com.java.java8.func.reduce.bean.Bar;
import com.java.java8.func.reduce.bean.Foo;

import java.util.List;
import java.util.stream.Collectors;


/*
 https://segmentfault.com/a/1190000008184585#articleHeader4
---背景 
 平时在编写前端代码时，习惯使用lodash来编写‘野生’的JavaScript;

lodash提供来一套完整的API对JS对象（Array,Object,Collection等）进行操作，这其中就包括_.groupBy 和 _.reduce，即分组和'聚合'（reduce不知道该怎么翻译合适）。

使用这些‘野生’的API能够极大的提高我本人编写JS代码的效率。而JAVA8开始支持stream和lambda表达式，这些和lodash的API有很多类似的功能。因此我在熟悉lodash的前提下尝试使用JAVA8的新特性减少冗余代码的编写。

---需求
在开发后端某功能接口的过程中，需要对一个从数据库中取出的数据List<T>进行按照ID进行聚合统计
*/

/*API个人理解
<U> U reduce(U u,BiFunction<U,? super T,U> accumulator,BinaryOperator<U> combiner)
#第一个参数返回实例u，传递你要返回的U类型对象的初始化实例u

#第二个参数累加器accumulator，可以使用二元ℷ表达式（即二元lambda表达式），声明你在u上累加你的数据来源t的逻辑
#例如(u,t)->u.sum(t),此时lambda表达式的行参列表是返回实例u和遍历的集合元素t，函数体是在u上累加t

#第三个参数组合器combiner，同样是二元ℷ表达式，(u,t)->u
#lambda表达式行参列表同样是(u,t)，函数体返回的类型则要和第一个参数的类型保持一致
伪代码
#1.声明一个返回结果U
#2.对List<T>进行遍历，在U和每个T实例上应用一个累加器进行累加操作
#3.返回最终结果U
U result = identity;
for (T element : this stream)
    result = accumulator.apply(result, element)
return result;*/


public class ReduceTest {
    
    public static void main(String[] args) throws Exception{
        List<Foo> fooList = Lists.newArrayList(
            new Foo("A","san",1.0,2),
            new Foo("A","nas",13.0,1),
            new Foo("B","san",112.0,3),
            new Foo("C","san",43.0,5),
            new Foo("B","nas",77.0,7)
        );
        List<Bar> barList = Lists.newArrayList();
        fooList
            .stream()
            .collect(Collectors.groupingBy(Foo::getName,Collectors.toList()))
            .forEach((name,fooListByName)->{
                Bar bar = new Bar();
                bar = fooListByName
                        .stream()
                        .reduce(bar,(u,t)->u.sum(t),(u,t)->u);
                System.out.println(bar.toString());
                barList.add(bar);
            });
    }
    /*
    输出结果
    name:A
    count:3
    totalTypeValue:14.0
    bazList:
        type:san
        typeValue:1.0
        type:nas
        typeValue:13.0
    
    name:B
    count:10
    totalTypeValue:189.0
    bazList:
        type:san
        typeValue:112.0
        type:nas
        typeValue:77.0
    
    name:C
    count:5
    totalTypeValue:43.0
    bazList:
        type:san
        typeValue:43.0
    */
}
